/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sentry.protocol;

import io.sentry.Span;
import io.sentry.SpanId;
import io.sentry.SpanStatus;
import io.sentry.util.CollectionUtils;
import io.sentry.util.Objects;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * SentrySpan
 *
 * @since 2021-06-02
 */
@ApiStatus.Internal
public final class SentrySpan {
    private final @NotNull Date startTimestamp;
    private final @Nullable Date timestamp;
    private final @NotNull SentryId traceId;
    private final @NotNull SpanId spanId;
    private final @Nullable SpanId parentSpanId;
    private final @NotNull String op;
    private final @Nullable String description;
    private final @Nullable SpanStatus status;
    private final @NotNull Map<String, String> tags;

    /**
     * constructor
     *
     * @param span span
     */
    public SentrySpan(final @NotNull Span span) {
        Objects.requireNonNull(span, "span is required");
        this.description = span.getDescription();
        this.op = span.getOperation();
        this.spanId = span.getSpanId();
        this.parentSpanId = span.getParentSpanId();
        this.traceId = span.getTraceId();
        this.status = span.getStatus();
        final Map<String, String> tagsCopy = CollectionUtils.newConcurrentHashMap(span.getTags());
        this.tags = tagsCopy != null ? tagsCopy : new ConcurrentHashMap<>();
        this.timestamp = span.getTimestamp();
        this.startTimestamp = span.getStartTimestamp();
    }

    /**
     * isFinished
     *
     * @return boolean
     */
    public boolean isFinished() {
        return this.timestamp != null;
    }

    public @NotNull Date getStartTimestamp() {
        return (Date) startTimestamp.clone();
    }

    public @Nullable Date getTimestamp() {
        return (Date) timestamp.clone();
    }

    public @NotNull SentryId getTraceId() {
        return traceId;
    }

    public @NotNull SpanId getSpanId() {
        return spanId;
    }

    public @Nullable SpanId getParentSpanId() {
        return parentSpanId;
    }

    public @NotNull String getOp() {
        return op;
    }

    public @Nullable String getDescription() {
        return description;
    }

    public @Nullable SpanStatus getStatus() {
        return status;
    }

    public @NotNull Map<String, String> getTags() {
        return tags;
    }
}
